
package com.hlkj.pay.app.merchant.ext.impl.alipayZft.ext;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;

import com.alipay.api.AlipayClient;
import com.alipay.api.domain.AlipayTradeCloseModel;
import com.alipay.api.domain.AlipayTradeFastpayRefundQueryModel;
import com.alipay.api.domain.AlipayTradeQueryModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.request.AlipayTradeCloseRequest;
import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeCloseResponse;
import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.hlkj.framework.caches.service.RedisTemplateService;
import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelPayOrderQueryContext;
import com.hlkj.pay.app.merchant.ext.dto.order.ChannelRefundPayOrderContext;
import com.hlkj.pay.app.merchant.ext.impl.alipay.dto.AlipayConfig;
import com.hlkj.pay.app.merchant.ext.impl.alipay.handler.AliPayCommonParamsHandle;
import com.hlkj.pay.app.merchant.ext.impl.alipayZft.dto.AliPayZftChannelParams;
import com.hlkj.pay.common.constants.RedisConstants;
import com.hlkj.pay.enums.PayOrderEnums;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAppChannelDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.order.RefundOrderDO;
import com.hlkj.pay.task.CommonTasks;
import com.hlkj.pay.util.DateUtils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 支付宝直付通支付 正扫 反扫 通用处理
 * 
 * @author HlpayTeam
 * @date 2024/10/11 16:22
 */
@Slf4j
@Repository
@RequiredArgsConstructor
public class AlipayZftSceneCommonPayOrder {

    @Autowired
    private AliPayCommonParamsHandle aliPayCommonParamsHandle;

    @Autowired
    private RedisTemplateService redisTemplateService;

    @Autowired
    private CommonTasks commonTasks;

    @Value("${hlkj.domain}")
    private String domain;
    /**
     * 支付宝直付通支付查询支付订单
     * 
     * @param channelPayOrderQueryContext
     */
    public void commonQueryChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        log.info("支付宝直付通订单查询 请求参数:{}", JsonUtils.toJsonString(channelPayOrderQueryContext));
        // 判断商户类型
        MerchantAppChannelDO merchantAppChannelDO = channelPayOrderQueryContext.getMerchantAppChannelDO();
        // 是否普通商户
        boolean common = aliPayCommonParamsHandle.commonMer(merchantAppChannelDO);
        // 支付宝直付通配置信息
        CommonResult<AlipayConfig> alipayConfigCommonResult = null;
        // 普通商户
        if(common){
            channelPayOrderQueryContext.setRemark("支付宝直付通不支持普通商户");
            channelPayOrderQueryContext.setProcessStatus(false);
            return;
        }else{
            alipayConfigCommonResult = aliPayCommonParamsHandle.alipayConfig(channelPayOrderQueryContext.getProviderChannelConfigDO().getParamsConfig());
        }
        if(!alipayConfigCommonResult.isSuccess()){
            channelPayOrderQueryContext.setRemark(alipayConfigCommonResult.getMsg());
            channelPayOrderQueryContext.setProcessStatus(false);
            return;
        }
        PayOrderDO payOrderDO = channelPayOrderQueryContext.getPayOrderDO();
        try {
            // 服务商
            AliPayZftChannelParams aliPayChannelParams = JsonUtils.parseObject(merchantAppChannelDO.getAppConfigJson(), AliPayZftChannelParams.class);
            // 获取AlipayClient
            AlipayClient client = aliPayCommonParamsHandle.initClient(alipayConfigCommonResult.getData());
            // 构造请求参数以调用接口
            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
            // 请求参数
            AlipayTradeQueryModel model = new AlipayTradeQueryModel();
            model.setOutTradeNo(payOrderDO.getPayOrderNo());
            // 设置查询选项
            List<String> queryOptions = new ArrayList<String>();
            queryOptions.add("trade_settle_info");
            model.setQueryOptions(queryOptions);

            request.setBizModel(model);

            log.info("服务商支付宝直付通订单查询 请求参数:{}", JSONUtil.toJsonStr(model));
            AlipayTradeQueryResponse response = client.execute(request);
            log.info("支付宝直付通订单查询 响应参数:{}", JSONUtil.toJsonStr(response));

            if(response.isSuccess()){
                PayOrderDO updartePayOrderDO = new PayOrderDO();
                switch (response.getTradeStatus()) {
                    case "WAIT_BUYER_PAY":
                        updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.PAYING.getCode());
                        updartePayOrderDO.setBankMsg("");
                        break;
                    case "TRADE_SUCCESS":
                        updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.SUCCESS.getCode());
                        updartePayOrderDO.setBankMsg("");
                        // 更新交易流水号
                        payOrderDO.setChannelOrderNo(response.getTradeNo());
                        // 缓存交易号，后续回调使用
                        if(StrUtil.isNotEmpty(response.getTradeNo())){
                            // 存入redis
                            redisTemplateService.hSet("pay_system:"+RedisConstants.PAY_ORDER_INFO+":channelOrderNo",response.getTradeNo(),payOrderDO,30*24*60*60);
                        }
                        // 资金结算
                        commonTasks.alipayZftSettleConfirm(client,payOrderDO,aliPayChannelParams.getSettleNo(),alipayConfigCommonResult.getData());
                        break;
                    case "TRADE_FINISHED":
                    case "TRADE_CLOSED":
                        updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.CLOSE.getCode());
                        break;
                }
                // 成功时间
                if (response.getSendPayDate() != null) {
                    updartePayOrderDO.setSuccessTime(DateUtils.shanghaiDate(DateUtil.format(response.getSendPayDate(), DatePattern.NORM_DATETIME_PATTERN),DatePattern.NORM_DATETIME_PATTERN));
                }
                updartePayOrderDO.setChannelOrderNo(response.getTradeNo());
                if (StrUtil.isNotEmpty(response.getTotalAmount())) {
                    updartePayOrderDO.setSettlementAmount(new BigDecimal(response.getReceiptAmount()));
                    updartePayOrderDO.setPayAmount(new BigDecimal(response.getTotalAmount()));
                }
                if (StrUtil.isNotEmpty(response.getBuyerOpenId())) {
                    updartePayOrderDO.setUserId(response.getBuyerOpenId());
                }
                channelPayOrderQueryContext.setUpdartePayOrderDO(updartePayOrderDO);

            }else{
                channelPayOrderQueryContext.setProcessStatus(Boolean.FALSE);
                channelPayOrderQueryContext.setRemark(response.getSubMsg());
            }
        }catch (Exception e){
            log.error("支付宝直付通查询支付订单请求失败 message:{}", e.getMessage(), e);
            channelPayOrderQueryContext.setRemark("支付宝直付通查询支付订单请求失败,失败信息" + e.getMessage());
            channelPayOrderQueryContext.setProcessStatus(Boolean.FALSE);
        }

    }

    /**
     * 支付宝直付通支付关闭订单
     * 
     * @param channelPayOrderQueryContext
     */
    public void commonCloseChannelPayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        log.info("支付宝直付通订单关闭 请求参数:{}", JsonUtils.toJsonString(channelPayOrderQueryContext));
        // 判断商户类型
        MerchantAppChannelDO merchantAppChannelDO = channelPayOrderQueryContext.getMerchantAppChannelDO();
        // 是否普通商户
        boolean common = aliPayCommonParamsHandle.commonMer(merchantAppChannelDO);
        // 支付宝直付通配置信息
        CommonResult<AlipayConfig> alipayConfigCommonResult = null;
        // 普通商户
        if(common){
            channelPayOrderQueryContext.setRemark("支付宝直付通不支持普通商户");
            channelPayOrderQueryContext.setProcessStatus(false);
            return;
        }else{
            alipayConfigCommonResult = aliPayCommonParamsHandle.alipayConfig(channelPayOrderQueryContext.getProviderChannelConfigDO().getParamsConfig());
        }
        if(!alipayConfigCommonResult.isSuccess()){
            channelPayOrderQueryContext.setRemark(alipayConfigCommonResult.getMsg());
            channelPayOrderQueryContext.setProcessStatus(false);
            return;
        }
        PayOrderDO payOrderDO = channelPayOrderQueryContext.getPayOrderDO();
        try {
            // 获取AlipayClient
            AlipayClient client = aliPayCommonParamsHandle.initClient(alipayConfigCommonResult.getData());
            AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
            // 请求参数
            AlipayTradeCloseModel model = new AlipayTradeCloseModel();
            model.setOutTradeNo(payOrderDO.getPayOrderNo());
            request.setBizModel(model);
            log.info("服务商支付宝直付通订单关闭 请求参数:{}", JSONUtil.toJsonStr(model));
            AlipayTradeCloseResponse response = client.execute(request);
            log.info("支付宝直付通订单关闭 响应参数:{}", JSONUtil.toJsonStr(response));

            if(response.isSuccess()){
                PayOrderDO updartePayOrderDO = new PayOrderDO();
                updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.CLOSE.getCode());
                channelPayOrderQueryContext.setUpdartePayOrderDO(updartePayOrderDO);
            }else{
                channelPayOrderQueryContext.setProcessStatus(Boolean.FALSE);
                channelPayOrderQueryContext.setRemark(response.getSubMsg());
            }
        }catch (Exception e){
            log.error("支付宝直付通订单关闭请求失败 message:{}", e);
            channelPayOrderQueryContext.setRemark("支付宝直付通查询支付订单请求失败,失败信息" + e.getMessage());
            channelPayOrderQueryContext.setProcessStatus(Boolean.FALSE);
        }
    }

    /**
     * 支付宝直付通支付查询关闭订单状态
     * 
     * @param channelPayOrderQueryContext
     */
    public void commonQueryChannelClosePayOrder(ChannelPayOrderQueryContext channelPayOrderQueryContext) {
        PayOrderDO updartePayOrderDO = new PayOrderDO();
        updartePayOrderDO.setState(PayOrderEnums.PAY_ORDER_STATUS.CLOSE.getCode());
        channelPayOrderQueryContext.setUpdartePayOrderDO(updartePayOrderDO);
    }

    /**
     * 支付宝直付通支付订单退款
     * 
     * @param channelRefundPayOrderContext
     */
    public void commonRefundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {

        log.info("支付宝直付通订单退款 请求参数:{}", JsonUtils.toJsonString(channelRefundPayOrderContext));
        // 判断商户类型
        MerchantAppChannelDO merchantAppChannelDO = channelRefundPayOrderContext.getMerchantAppChannelDO();
        // 是否普通商户
        boolean common = aliPayCommonParamsHandle.commonMer(merchantAppChannelDO);
        // 支付宝直付通配置信息
        CommonResult<AlipayConfig> alipayConfigCommonResult = null;
        // 普通商户
        if(common){
            channelRefundPayOrderContext.setRemark("支付宝直付通不支持普通商户");
            channelRefundPayOrderContext.setProcessStatus(false);
            return;
        }else{
            alipayConfigCommonResult = aliPayCommonParamsHandle.alipayConfig(channelRefundPayOrderContext.getProviderChannelConfigDO().getParamsConfig());
        }
        if(!alipayConfigCommonResult.isSuccess()){
            channelRefundPayOrderContext.setRemark(alipayConfigCommonResult.getMsg());
            channelRefundPayOrderContext.setProcessStatus(false);
            return;
        }
        PayOrderDO payOrderDO = channelRefundPayOrderContext.getPayOrderDO();
        RefundOrderDO refundOrderDO = channelRefundPayOrderContext.getRefundOrderDO();
        try {
            // 获取AlipayClient
            AlipayClient client = aliPayCommonParamsHandle.initClient(alipayConfigCommonResult.getData());
            // 构造请求参数以调用接口
            AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
            // 请求参数
            AlipayTradeRefundModel model = new AlipayTradeRefundModel();
            model.setOutTradeNo(payOrderDO.getPayOrderNo());
            model.setRefundAmount(NumberUtil.roundStr(refundOrderDO.getRefundAmount().doubleValue(),2));
            model.setRefundReason(refundOrderDO.getRefundReason());
            model.setOutRequestNo(refundOrderDO.getRefundOrderNo());
            request.setNotifyUrl(channelRefundPayOrderContext.getNotifyUrl());
            request.setBizModel(model);
            log.info("服务商支付宝直付通订单退款 请求参数:{}", JSONUtil.toJsonStr(model));
            AlipayTradeRefundResponse response = client.execute(request);
            log.info("支付宝直付通订单退款 响应参数:{}", JSONUtil.toJsonStr(response));

            if(response.isSuccess()){
                RefundOrderDO updateRefundOrderDO = new RefundOrderDO();
                if(response.getFundChange().equals("Y")){
                    updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.REFUND.getCode());
                    channelRefundPayOrderContext.setUpdateRefundOrderDO(updateRefundOrderDO);
                }else{
                    updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.REFUNDING.getCode());
                    channelRefundPayOrderContext.setUpdateRefundOrderDO(updateRefundOrderDO);
                }
            }else{
                channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
                channelRefundPayOrderContext.setRemark(response.getSubMsg());
            }
        }catch (Exception e){
            log.error("支付宝直付通支付宝直付通订单退款请求失败 message:{}", e);
            channelRefundPayOrderContext.setRemark("支付宝直付通支付宝直付通订单退款请求失败,失败信息" + e.getMessage());
            channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }

    /**
     * 支付宝直付通支付订单退款状态查询
     * 
     * @param channelRefundPayOrderContext
     */
    public void commonQueryRefundChannelPayOrder(ChannelRefundPayOrderContext channelRefundPayOrderContext) {

        log.info("支付宝直付通订单退款查询 请求参数:{}", JsonUtils.toJsonString(channelRefundPayOrderContext));
        // 判断商户类型
        MerchantAppChannelDO merchantAppChannelDO = channelRefundPayOrderContext.getMerchantAppChannelDO();
        // 是否普通商户
        boolean common = aliPayCommonParamsHandle.commonMer(merchantAppChannelDO);
        // 支付宝直付通配置信息
        CommonResult<AlipayConfig> alipayConfigCommonResult = null;
        // 普通商户
        if(common){
            channelRefundPayOrderContext.setRemark("支付宝直付通不支持普通商户");
            channelRefundPayOrderContext.setProcessStatus(false);
            return;
        }else{
            alipayConfigCommonResult = aliPayCommonParamsHandle.alipayConfig(channelRefundPayOrderContext.getProviderChannelConfigDO().getParamsConfig());
        }
        if(!alipayConfigCommonResult.isSuccess()){
            channelRefundPayOrderContext.setRemark(alipayConfigCommonResult.getMsg());
            channelRefundPayOrderContext.setProcessStatus(false);
            return;
        }
        PayOrderDO payOrderDO = channelRefundPayOrderContext.getPayOrderDO();
        RefundOrderDO refundOrderDO = channelRefundPayOrderContext.getRefundOrderDO();
        try {
            // 获取AlipayClient
            AlipayClient client = aliPayCommonParamsHandle.initClient(alipayConfigCommonResult.getData());
            AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
            // 请求参数
            AlipayTradeFastpayRefundQueryModel model = new AlipayTradeFastpayRefundQueryModel ();
            model.setOutTradeNo(payOrderDO.getPayOrderNo());
            model.setOutRequestNo(refundOrderDO.getRefundOrderNo());
            model.setQueryOptions(CollUtil.newArrayList("gmt_refund_pay","refund_detail_item_list"));
            request.setBizModel(model);

            log.info("服务商支付宝直付通订单退款查询 请求参数:{}", JSONUtil.toJsonStr(model));
            AlipayTradeFastpayRefundQueryResponse response = client.execute(request);
            log.info("支付宝直付通订单退款查询 响应参数:{}", JSONUtil.toJsonStr(response));

            if(response.isSuccess()){
                RefundOrderDO updateRefundOrderDO = new RefundOrderDO();
                switch (response.getRefundStatus()){
                    case "REFUND_SUCCESS":
                        updateRefundOrderDO.setRefundStatus(PayOrderEnums.REFUND_STATUS.REFUND.getCode());
                        updateRefundOrderDO.setSuccessTime(DateUtils.shanghaiDate(DateUtil.format(response.getGmtRefundPay(), DatePattern.NORM_DATETIME_PATTERN),DatePattern.NORM_DATETIME_PATTERN));
                        break;
                }
                channelRefundPayOrderContext.setUpdateRefundOrderDO(updateRefundOrderDO);
            }else{
                channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
                channelRefundPayOrderContext.setRemark(response.getSubMsg());
            }

        }catch (Exception e){
            log.error("支付宝直付通支付查询退款请求失败 message:{}",  e);
            channelRefundPayOrderContext.setRemark("支付宝直付通支付查询退款请求失败,失败信息" + e.getMessage());
            channelRefundPayOrderContext.setProcessStatus(Boolean.FALSE);
        }
    }


}
